package com.tbit.main.controller;

import cn.hutool.core.util.DesensitizedUtil;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.common.utils.Utf8Mb4Checker;
import com.tbit.main.constant.OperaPswConstant;
import com.tbit.main.constant.RedisConstant;
import com.tbit.main.constant.UserConstant;
import com.tbit.main.dao.capital.RideLogDetailsDao;
import com.tbit.main.dao.core.UserDao;
import com.tbit.main.pojo.*;
import com.tbit.main.controller.interceptor.LoginUserContextHolder;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.VO.UserVO;
import com.tbit.main.service.*;
import com.tbit.main.service.manager.util.StringUtils;
import com.tbit.manager.api.UserApi;
import com.tbit.manager.api.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * 用户管理
 *
 * @author ：zhangtianyou
 * @since 2024/11/22
 */
@Slf4j
@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private UserApi userApi;
    @Autowired
    private UserDao userDao;
    @Autowired
    private RideLogDetailsDao rideLogDetailsDao;
    @Autowired
    private UserFaceDataService userFaceDataService;
    @Autowired
    private OperaPswService operaPswService;

    /**
     * 用户信息查询
     *
     * @param name         姓名
     * @param idNo         身份证号
     * @param userCode     车辆编号
     * @param rowCount     每页行数
     * @param pageNO       页码
     * @param phone        手机号
     * @param nameAuth     实名认证状态
     * @param depositState 押金状态
     * @param startTime    开始时间
     * @param endTime      结束时间
     * @param mapType      地图类型 默认 2:高德
     */
    @GetMapping("/queryPage")
    public Result<List<UserVO>> queryPage(String name, String idNo, String userCode,
                                          @RequestParam(defaultValue = "10") Integer rowCount,
                                          Integer userId,
                                          @RequestParam(defaultValue = "1") Integer pageNO, String phone,
                                          Integer nameAuth, Integer depositState, Long startTime, Long endTime,
                                          @RequestParam(name = "mapType", defaultValue = "2", required = false) Integer mapType) {
        if (StringUtils.isEmpty(name) && StringUtils.isEmpty(idNo) && StringUtils.isEmpty(phone) && userId == null){
            throw new BaseException("user_not_exit");
        }
        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        if (userCode != null) {
            Machine machine = machineService.getByUseCode(userCode);
            if (machine != null) {
                MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
                if (machineBorrow != null) {
                    phone = userService.getByUserId(machineBorrow.getUserId()).getPhone();
                }
            } else {
                throw new BaseException("machine_not_exist");
            }
        }
        //查询具体用户
        List<UserVO> users = userService.queryPage(loginUser, userId, phone, name, idNo, rowCount, pageNO, nameAuth,
                depositState, startTime, endTime, mapType);
        users.forEach(userVO -> {
            userVO.setIdNO(DesensitizedUtil.idCardNum(userVO.getIdNO(), 1, 4));
            //userVO.setPhone(DesensitizedUtil.mobilePhone(userVO.getPhone()));
        });

        return Result.success(users);
    }

    /**
     * 用户实名认证
     */
    @GetMapping("/nameAuth")
    public Result<String> nameAuth(@NotNull Integer userId, @NotNull String idNO, @NotNull String name) {
        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        userApi.updateNameAuth(userId, name, idNO, loginUser.getName(), loginUser.getPhone());
        return Result.success();
    }

    /**
     * 学生实名认证
     */
    @GetMapping("/studentAuth")
    public Result<String> studentAuth(@NotNull Integer userId, @NotBlank String studentIdNO) {
        userApi.updateStudentAuth(userId, 1, studentIdNO);
        return Result.success();
    }

    /**
     * 清空实名认证信息
     *
     * @param userId 用户id
     * @return Result
     */
    @GetMapping("/editNameAuth")
    public Result<String> editNameAuth(@NotNull Integer userId) {
        userApi.editNameAuth(userId);
        return Result.success();
    }

    /**
     * 清空实名认证提交次数
     *
     * @param userId 用户id
     * @return Result
     */
    @GetMapping("/editNameAuthCount")
    public Result<String> editNameAuthCount(@NotNull Integer userId) {
        userApi.editNameAuthCount(userId);
        return Result.success();
    }


    /**
     * 删除用户登录缓存
     *
     * @param userId   用户id
     * @param operaPsw 操作密码
     */
    @GetMapping("/deleteRedisLoginCache")
    public Result<String> deleteRedisLoginCache(@NotNull Integer userId, String operaPsw) {
        /**操作密码校验 兼容5.0.0之前版本 常量校验不通过时，再调接口校验*/
        if (!OperaPswConstant.ACCOUNT_OPERA_DEL_MACHINE.equals(operaPsw)) {
            operaPswService.checkOperaPsw(LoginUserContextHolder.getLoginUser(), OperaPswEnum.OPERA_PSW_OPERATION_CONFIG.getModule(),
                    operaPsw);
        }

        User user = userService.getByUserId(userId);
        if (user == null) {
            return Result.error("用户不存在");
        }
        String redisKey = new StringBuilder("USER")
                .append(":")
                .append(user.getAccountId())
                .append(":")
                .append(user.getUserId())
                .toString();
        String tokenValidKey = redisService.get(redisKey);
        if (StringUtils.isNotEmpty(tokenValidKey)) {
            redisService.del(tokenValidKey);
        }
        redisService.del(redisKey);
        return Result.success();
    }

    /**
     * 清除用户欠款
     *
     * @param userId   用户id
     * @param operaPsw 密钥
     */
    @GetMapping("/clearArrears")
    public Result<String> clearArrears(@NotNull Integer userId, String operaPsw) {
        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(userId);
        userDTO.setLoginUserAccountUserId(loginUser.getAccountUserId());
        userDTO.setLoginUserName(loginUser.getName());
        userDTO.setLoginUserPhone(loginUser.getPhone());
        userDTO.setLoginUserPlatform(OperationPlatform.MAINTAIN.code);
        /**操作密码校验 兼容5.0.0之前版本 常量校验不通过时，再调接口校验*/
        if (!OperaPswConstant.USER_OPERA_UPDATE_MONEY.equals(operaPsw)) {
            operaPswService.checkOperaPsw(LoginUserContextHolder.getLoginUser(), OperaPswEnum.OPERA_PSW_ORDER_CONFIG.getModule(),
                    operaPsw);
        }
        User user = userDao.getByUserId(userId);
        if (user == null) {
            return Result.error("user.not.exist");
        }
        if (user.getRideMoney() == null || user.getRideMoney() == 0) {
            return Result.error("用户无欠款");
        }
        if (user.getRideMoney() < 0) {
            return Result.error("用户欠款数据有误，请联系管理员处理");
        }
        RideLogDetails rideLogDetails = rideLogDetailsDao.queryLatestCyclingOrder(userId);
        if (rideLogDetails != null && rideLogDetails.getPayTime() != null) {
            return Result.error("用户欠款订单数据有误，请联系管理员处理");
        }
        Boolean result = userApi.clearArrears(userDTO);
        return result ? Result.success() : Result.error();
    }

    /**
     * 修改用户手机号码
     *
     * @param userId 用户id
     * @param phone  新手机号码
     * @param reason 原因
     */
    @GetMapping("/updatePhone")
    public Result<String> updatePhone(@NotNull Integer userId, @NotNull String phone, @NotNull String reason) {
        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(userId);
        userDTO.setPhone(phone);
        userDTO.setLoginUserAccountUserId(loginUser.getAccountUserId());
        userDTO.setReason(reason);
        userDTO.setLoginUserPlatform(OperationPlatform.MAINTAIN.code);
        userDTO.setLoginUserName(loginUser.getName());
        userDTO.setLoginUserPhone(loginUser.getPhone());
        Boolean result = userApi.updateUser(userDTO);
        return result ? Result.success() : Result.error();
    }

    /**
     * 余额修改
     *
     * @param userId   用户id
     * @param money    金额 扣款为负数（扣款20元：-2000）
     * @param remark   备注
     * @param operaPsw 操作密码
     */
    @GetMapping("/rechargeMoney")
    public Result<String> rechargeMoney(@NotNull Integer userId, @NotNull Integer money, @NotNull String remark, String operaPsw) {
        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        // 金额不能等于
        if (money == 0) {
            throw new BaseException("money.not.zero");
        }
        if (remark.length() > 200) {
            throw new BaseException("备注不能超过200个字符");
        }
        /**操作密码校验 兼容5.0.0之前版本 常量校验不通过时，再调接口校验*/
        if (!OperaPswConstant.USER_OPERA_UPDATE_MONEY.equals(operaPsw)) {
            operaPswService.checkOperaPsw(LoginUserContextHolder.getLoginUser(), OperaPswEnum.OPERA_PSW_MONEY_CONFIG.getModule(),
                    operaPsw);
        }
        User user = userDao.getByUserId(userId);
        if (user == null) {
            throw new BaseException("user.not.exist");
        }
        Double oldUserMoney = user.getMoney();
        Double newUserMoney = oldUserMoney + money;
        if (newUserMoney < 0) {
            throw new BaseException("用户余额不足");
        }
        //修改余额前判断备注否包含特殊字符
        if (Utf8Mb4Checker.containsUtf8mb4Chars(remark)) {
            throw new BaseException("备注含非法字符，请调整后再次发起");
        }

        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(userId);
        userDTO.setMoney(money);
        userDTO.setRemark(remark);
        userDTO.setOperaPsw(operaPsw);
        userDTO.setLoginUserAccountUserId(loginUser.getAccountUserId());
        userDTO.setLoginUserType(loginUser.getAccountUserType());
        userDTO.setLoginUserName(loginUser.getUserName());
        userDTO.setLoginUserPhone(loginUser.getPhone());
        userDTO.setAccountId(loginUser.getAccountId());
        userDTO.setLoginUserPlatform(3);
        userApi.rechargeMoney(userDTO);
        return Result.success();
    }

    /**
     * 押金冻结
     *
     * @param userId       用户id
     * @param depositState 押金状态 (0:未提交押金;1:已提交押金;2:押金退还中;3:芝麻信用;4:押金冻结;5:学生认证免押金)
     */
    @GetMapping("/frozenDeposit")
    public Result<String> frozenDeposit(@NotNull(message = "ver.userId.notNull") Integer userId,
                                        @NotNull(message = "ver.depositState.notNull") Integer depositState) {

        AccountUser loginUser = LoginUserContextHolder.getLoginUser();
        // 获取用户信息
        if (!UserConstant.ACCOUNT_ADMIN.equals(loginUser.getAccountUserType()) &&
                !UserConstant.ACCOUNT_BRAND.equals(loginUser.getAccountUserType())) {
            throw new BaseException("System.noPower");
        }

        //验证
        User user = userService.getByUserId(userId);
        if (!UserConstant.ACCOUNT_BRAND.equals(loginUser.getAccountUserType())) {
            if (!user.getAccountId().equals(loginUser.getAccountId())) {
                throw new BaseException("System.noPower");
            }
        }
        userApi.frozenDeposit(userId, depositState);

        return Result.success();
    }

    /**
     * 根据用户id删除用户人脸缓存
     *
     * @param userId 用户id
     */
    @GetMapping("/deleteFaceCacheByUserId")
    public Result<String> deleteFaceCacheByUserId(@NotNull(message = "ver.userId.notNull") Integer userId) {

        userFaceDataService.deleteFaceCacheByUserId(userId);
        // 清空人脸识别次数
        redisService.del(RedisConstant.FACE_CHECK + "_" + userId);

        return Result.success();
    }

}
